package com.turing.model.caller.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.turing.common.config.ServerConfig;
import com.turing.common.response.ResponseVO;
import com.turing.common.response.model.ResVO;
import com.turing.common.util.HttpUtils;
import com.turing.model.caller.rules.IRule;
import com.turing.model.caller.service.DrawService;
import com.turing.model.caller.service.ModelService;
import com.turing.model.caller.service.OcrService;
import com.turing.model.caller.task.OcrResultCallBack;
import com.turing.model.caller.utils.SpringUtil;
import com.turing.model.caller.vo.in.OcrPageTask;
import com.turing.model.caller.vo.in.OcrResultEntity;
import com.turing.model.caller.vo.in.OcrResultVo;
import com.turing.model.caller.vo.out.OcrCallParamsVo;
import com.xxl.job.core.context.XxlJobHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class OcrServiceImpl implements OcrService {



    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private OcrResultCallBack ocrResultCallBack;

    @Autowired
    private DrawService drawService;

    @Autowired
    private ModelService modelService;

    private static final Logger logger = LoggerFactory.getLogger(OcrServiceImpl.class);

    @Value("${producer.clients:}")
    private List<String> clients;

    @Value("${loadBalance.rule}")
    private String balanceRule;

    @Override
    public void process() {

        // choose client
        IRule rule = (IRule) SpringUtil.getBean(balanceRule);
        String client = rule.choose(clients);

        // try to get task
        String url = serverConfig.getUrl();
        ResponseVO<OcrPageTask> getResVO = null;

        try{
            getResVO = drawService.getAndLockOcrPageTask(url,client);
        }catch (Exception e){
            e.printStackTrace();
        }

        if(getResVO !=null && getResVO.getCode().equals("200")){
            OcrPageTask ocrPageTask = getResVO.getData();
            if(ocrPageTask == null){
                // retry
                client = rule.choose(clients);
                getResVO = drawService.getAndLockOcrPageTask(url,client);
                if(getResVO !=null && getResVO.getCode().equals("200")){
                    ocrPageTask = getResVO.getData();
                }
            }
            if(ocrPageTask != null){

                String ocrPageTaskSn = ocrPageTask.getOcrPageTaskSn();
                String imageUrl = ocrPageTask.getImageUrl();
                Integer pageNo = ocrPageTask.getPageNo();
                String taskSn = ocrPageTask.getTaskSn();
                String templateId = ocrPageTask.getTemplateId();
                String parentTaskSn = ocrPageTask.getParentTaskSn();

                // call model
                String param = XxlJobHelper.getJobParam();
                logger.info("param:"+param);
                String[] split = param.split("_");

                // test model ok
//                if((templateId.equals("2") && modelService.statusOK("127.0.0.1:1101","0"))
                if(( templateId.equals("2") || modelService.statusOK("127.0.0.1:1101","0"))
                         ){
                    // String httpUrl = "http://" +split[0] + "/api/model/ocr";
                    String httpUrl = "";
                    if(templateId.equals("2")){
                        httpUrl = "http://127.0.0.1:1101/api/model/ocr";
                    }else {
                        httpUrl = "http://" +split[0] + "/api/model/ocr";
                    }
                    httpUrl = "http://127.0.0.1:1101/api/model/ocr";
                    logger.info("=================>template is {} , httpUrl is {}",templateId,httpUrl);
                    OcrCallParamsVo callParam = OcrCallParamsVo.builder()
                            .task_id(parentTaskSn)
                            .element_id(templateId)
                            .gpu_id(split[1])
                            .file_id(imageUrl)
                            .file_name(imageUrl.substring(imageUrl.lastIndexOf("/")+1))
                            .page(String.valueOf(pageNo)).build();
                    if("com.turing.model.caller.client.task.manager.OcrClient".equals(client)){
                        callParam.setDouble_pdf(1);
                        logger.info("=======> 单独ocr，双层pdf 调用 +请求参数："+callParam);
                    }
                    int readTimeOut = 600000;
                    String params = JSON.toJSONString(callParam);
                    logger.info("thread id is:"+Thread.currentThread().getId()+",starting call ocr model , taskSn is:"+taskSn+" file_Name:"+callParam.getFile_name()+"pageNo is:"+pageNo+",card no is:"+split[1]);
                    String res = "";
                    try{
                        res = HttpUtils.doPost(httpUrl,params,readTimeOut);
                    }catch (Exception e){
                        logger.error(e.getMessage());
                        ResponseVO<Object> responseOk = null;
                        try{
                            responseOk = drawService.unLockOcrPageTask(ocrPageTaskSn,url);
                        }catch (Exception e1){
                            logger.error(e1.getMessage());
                        }

                        logger.info("thread id is:"+Thread.currentThread().getId()+",unlock result:"+responseOk.getData().toString()+",card no is:"+split[1]);
                        return;
                    }

                    ResVO<String> ocrResVo = JSONObject.parseObject(res, new TypeReference<ResVO<String>>(){});
                    String resCode = ocrResVo.getCode();
                    logger.info("thread id is:"+Thread.currentThread().getId()+",taskSn is:"+taskSn+","+"resCode is:"+resCode+",pageNo is:"+pageNo+",card no is:"+split[1]);
                    if(resCode.equals("0")){
                        // success callback
                        String ocrEntity = ocrResVo.getData();
                        OcrResultEntity ocrResultEntity = JSONObject.parseObject(ocrEntity, OcrResultEntity.class);

                        OcrResultVo ocrResultVo = OcrResultVo.builder().ocrPageTaskSn(ocrPageTaskSn)
                                .pageNo(pageNo)
                                .taskSn(taskSn)
                                .JSONText(JSON.toJSONString(ocrResultEntity.getPage_json()))
                                .imageUrl(ocrResultEntity.getImg_file_id())
                                .imgWidth(ocrResultEntity.getImg_info().getSize()[0])
                                .imgHeight(ocrResultEntity.getImg_info().getSize()[1])
                                .templateId(templateId)
                                .build();
                        if("com.turing.model.caller.client.task.manager.OcrClient".equals(client)){
                            ocrResultVo.setDoubleDeckPdfUrl(ocrResultEntity.getDouble_pdf_file_id());
                            logger.info("=======>获取双层pdf完成，结果为："+ocrResultVo.getDoubleDeckPdfUrl());
                        }
                        logger.info("susessful doCallback");
                        ocrResultCallBack.doCallback(ocrResultVo,client);

                    }else{
                        logger.info("fail callback");
                        // fail callback
                        ResponseVO<Object> responseOk = null;
                        try{
                            responseOk = drawService.unLockOcrPageTask(ocrPageTaskSn,client);
                        }catch (Exception e){
                            logger.error(e.getMessage());
                        }
                        logger.info("thread id is:"+Thread.currentThread().getId()+",response not ok,unlock task,result is:"+responseOk.getData().toString()+",card no is:"+split[1]);
                    }
                }else{
                    drawService.unLockOcrPageTask(ocrPageTaskSn,client);
                }
            }
        }
    }

}
